#include "server.h"
#include "sys_socket.h"
#include <iostream>
using std::cerr;
using std::endl;

Server::Server(unsigned int port):
    m_port(port)
{
    // ctor
    m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (m_sock != -1) {
        // bind
        sockaddr_in addr;
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(m_port);
        if ((-1 == bind(m_sock, (sockaddr*)&addr, sizeof(addr))) ||
            (-1 == listen(m_sock, 10))) {
            cerr << "Bind or listen failed" << endl;
            closesocket(m_sock);
            m_sock = -1;
        }
    }
}

Server::~Server()
{
    stop();
}

static bool isUselessHandler(ClientHandler* handler)
{
    if (handler->isStopped()) {
        delete handler;
        return true;
    }
    return false;
}

void Server::run()
{
    // wait for connections, create a thread for each connection
    while (true) {
        sockaddr_in addr;
        socklen_t addrlen = sizeof(addr);
        int rc = accept(m_sock, (sockaddr*)&addr, &addrlen);
        if (rc < 0) {
            cerr << "Accept failed" << endl;
            break;
        }
        // remove useless handlers
        m_handlers.remove_if(isUselessHandler);
        ClientHandler* handler = new ClientHandler(rc);
        m_handlers.push_back(handler);
        handler->start();
    }
}

void Server::stop()
{
    if (m_sock != -1) {
        closesocket(m_sock);
        m_sock = -1;

        // stop all handlers
        while (m_handlers.size() > 0) {
            ClientHandler* handler = m_handlers.front();
            delete handler;
            m_handlers.pop_front();
        }
        join();
    }
}
